/****************************************************************************
**
** Copyright (C) 2013 Atmel Corporation and/or its subsidiary(-ies).
** All rights reserved.
**
** LIMITED License Agreement
**
** IT IS IMPORTANT THAT YOU READ THIS AGREEMENT CAREFULLY AND COMPLETELY.
** This Limited License Agreement (“Agreement”) is a legally binding agreement between,
** on one hand, either your employer (if you are acting on behalf of your employer)
** or you (if you are acting on your own behalf) (“Licensee”), and on the other hand,
** Atmel Corporation (“Atmel”).
**
** By installing or using any of the software downloaded or provided with these
** terms (“Licensed Software”), you are indicating that you are binding Licensee
** to the terms of this Agreement, and that you are duly authorized by Licensee to do so.
** If you are not authorized to bind Licensee to the terms of this Agreement,
** or if Licensee does not agree to be bound by all of the terms of this Agreement,
** do not install or use any such software.
**
**
** 1.	Grant of License.  Subject to the terms and conditions of this Agreement,
** Atmel grants Licensee a non-exclusive, non-transferable, non-sublicensable,
** limited license to use the Licensed Software solely in connection with Atmel products
** from SAM9 and SAMA5 families (“Atmel Product”).
**
** 2.	Restrictions.  Except as expressly set forth in Section 1, Licensee will not,
** and will have no right to, (a) use, copy or reproduce any Licensed Software except,
** (b) modify, create derivative works of, sell, distribute, transfer or disclose any
** Licensed Software. Without limiting the generality of the foregoing, Licensee will not,
** and will have no right to, use any Licensed Software for any semiconductor products
** that are not Atmel Products. Licensee will not remove, obscure or alter any trademark,
** copyright or other proprietary rights or ownership notices of Atmel that appear
** in any Licensed Software.
**
** 3.  	Title.  As between the parties, Atmel retains full rights, title, and ownership
** including all patents, copyrights, trade secrets, trade names, trademarks, and other
** intellectual property rights in and to the Licensed Software.
**
** 4.  	No Other Rights.  Except as expressly stated herein, this Agreement does not grant
** Licensee any rights to patents, copyrights, trade secrets, trade names, trademarks
** (whether registered or unregistered), or any other rights, franchises, or licenses
** in respect of the Licensed Software.
**
** 5.	Disclaimer of Warranty and No Support.  ALL LICENSED SOFTWARE IS PROVIDED “AS IS”,
** “WITH ALL FAULTS”, AND WITH NO WARRANTY WHATSOEVER.  ATMEL EXPRESSLY DISCLAIMS ALL
** WARRANTIES OF ANY KIND (WHEHTER EXPRESS, IMPLIED, STATUTORY OR OTHERWISE) IN CONNECTION
** WITH THE LICENSED SOFTWARE OR ANY OTHER ASPECT OF THIS AGREEMENT, INCLUDING, WITHOUT
** LIMITATION ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
** TITLE OR NON-INFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY WARRANTIES THAT MAY ARISE
** FROM COURSE OF DEALING, COURSE OF PERFORMANCE OR USAGE OF TRADE.  ATMEL WILL HAVE
** NO OBLIGATION UNDER THIS AGREEMENT TO CORRECT ANY BUGS, DEFECTS OR ERRORS IN
** THE LICENSED SOFTWARE, PROVIDE ANY UPDATES, UPGRADES OR NEW RELEASES OF THE LICENSED SOFTWARE,
** OR OTHERWISE PROVIDE ANY SUPPORT OR MAINTENANCE FOR THE LICENSED SOFTWARE.
**
** 6.  	Export.  Licensee will comply with all applicable laws and regulations of all
** relevant jurisdictions in connection with its activities related to the Licensed Software.
** Without limitation of the foregoing, Licensee acknowledges that certain laws
** and regulations of the United States and other jurisdictions may pertain to the export
** and re-export of the Licensed Software, and Licensee will not export or re-export
** any Licensed Software in any form without the appropriate governmental approvals,
** or otherwise in violation of any such laws or regulations.
**
** 7.	Termination.  The license will automatically terminate if Licensee fails to comply
** with any of the terms and conditions of the license including, without limitation
** the confidentiality obligation or the obligations set forth in Sections 1, 2, 6, 7, 10
** and 11 herein. Upon termination for any reason, Licensee will immediately destroy
** or return to Atmel all whole or partial copies of the Licensed Software.
**
** 8.	High Risk Activities. LICENSEE ACKNOWLEDGES AND AGREES THAT THE LICENSED SOFTWARE
** IS NOT DESIGNED OR APPROVED FOR, AND WILL NOT BE INCORPORATED (WITHOUT THE EXPRESS WRITTEN
** APPROVAL OF AN OFFICER OF ATMEL) INTO, ANY PRODUCTS THAT ARE USED OR DESIGNED TO BE USED
** IN CONNECTION WITH ANY ACTIVITIES WHERE THE FAILURE OF SUCH PRODUCTS COULD REASONABLY
** BE EXPECTED TO RESULT IN DEATH, BODILY INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE
** ("HIGH RISK ACTIVITIES").  IN NO EVENT WILL ATMEL HAVE ANY LIABILITY TO LICENSEE
** OR ANY THIRD PARTY ARISING OUT OF OR RELATED TO ANY USE OF LICENSED SOFTWARE IN CONNECTION
** WITH HIGH RISK ACTIVITIES, AND ATMEL HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF
** FITNESS FOR ANY HIGH RISK ACTIVITIES.
**
** 9.  	LIMITATION OF LIABILITY.  TO THE EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL
** ATMEL BE LIABLE TO LICENSEE OR ANY THIRD PARTY (WHETHER SUCH LIABILITY IS BASED ON CONTRACT,
** NEGLIGENCE, STRICT LIABILITY, OTHER TORT THEORY, CONTRIBUTION, BREACH OF WARRANTY,
** OR OTHER LEGAL OR EQUITABLE THEORY) FOR ANY SPECIAL, INDIRECT, INCIDENTAL, EXEMPLARY,
** PUNITIVE OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES FOR LOSS OF PROFITS,
** LOSS OR INTERRUPTION OF BUSINESS, OR LOSS OF DATA, ARISING OUT OF OR RELATING TO
** THE LICENSED SOFTWARE OR ANY OTHER ASPECT OF THIS AGREEMENT, EVEN IF ATMEL has been advised
** of or should have known of the possibility of such damages.
**
** IN NO EVENT WILL ATMEL’S TOTAL LIABILITY ARISING OUT OF OR RELATED TO THE LICENSED SOFTWARE
** OR ANY OTHER ASPECT OF THIS AGREEMENT (WHETHER UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY,
** CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL OR EQUITABLE THEORY) EXCEED THE GREATER OF
** (A) THE AGGREGATE OF ALL LICENSE FEES PAID BY LICENSEE TO ATMEL FOR THE LICENSED SOFTWARE, OR
** (B) ONE THOUSAND DOLLARS ($1,000). WITHOUT LIMITING THE FOREGOING,
** AND Notwithstanding any provision herein to the contrary, ATMEL will not be liable for
** ANY costs of PROCURING SUBSTITUTE GOODS, SERVICES OR TECHNOLOGY under any circumstances.
**
** Each Party acknowledges that THE OTHER PARTY has entered into this agreement in reliance
** on the limitations of liability, DISCLAIMERS OF WARRANTIES, EXCLUSION OF DAMAGES
** AND EXCLUSIVE REMEDIES contained in this AGREEMENT, AND THAT EACH OF THE FOREGOING PROVISIONS FORMS
** AN ESSENTIAL AND fundamental part of the basis of the bargain BETWEEN THE PARTIES,
** WITHOUT WHICH SUCH the other Party would not have entered into this Agreement.
** EACH PARTY AGREES THAT SUCH PROVISIONS WILL SURVIVE AND APPLY NOTWITHSTANDING ANY
** FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY OR LIMITATION OF LIABILITY.
**
** 10.  	Governing Law; Dispute Resolution. This Agreement is to be construed in accordance
** with and governed by the internal laws of the State of California (as permitted by Section 1646.5
** of the California Civil Code or any similar successor provision), without giving effect
** to any choice of law rule that would cause the application of the laws of any jurisdiction
** other than the internal laws of the State of California to the rights and duties of the parties.
** This Agreement will not be governed by the U.N. Convention on the Sale of Goods,
** the application of which is expressly excluded. Except for actions for injunctive
** or other equitable relief, which may be brought in any court of competent jurisdiction,
** all disputes arising out of or related to this Agreement will be subject to the exclusive
** jurisdiction of the California state courts in Santa Clara County, California,
** or if there is exclusive federal jurisdiction, the United States District Court for
** the Northern District of California, and the Parties hereby consent to, and agree to submit to,
** the personal and exclusive jurisdiction and venue of such courts.
**
** 11. 	General. Licensee will not, and will have no right to, assign, delegate or otherwise
** transfer (whether voluntarily, by operation of law or otherwise) this Agreement or any of
** its rights or obligations hereunder to any third party without the prior written consent
** of Atmel, and any purported assignment, delegation or other transfer without such consent
** will have no force or effect. Subject to the foregoing, this Agreement will be binding upon
** and will inure to the benefit of the parties and their respective successors and permitted assigns.
** No failure of either party to enforce any right under this Agreement will be deemed a waiver
** of such right or any other right under this Agreement. Any waiver by a party of a breach
** of any provision of this Agreement by the other party hereunder will not be deemed to be
** a waiver of any subsequent breach of such provision or a waiver of any breach of any other
** provision of this Agreement.
** This Agreement may not be superseded, modified, or amended except in a writing signed by an officer
** of each party. If any provision of this Agreement is determined to be invalid, illegal
** or otherwise unenforceable, such provision will be enforced to the extent possible consistent
** with the intent of the parties, and the remaining provisions of this Agreement will remain in
** full force and effect. This Agreement will be fairly interpreted in accordance with its terms
** and without any strict construction against either party because it was drafted by such party
** or for any other reason. This Agreement will constitute the entire agreement between the parties
** relating to the subject matter hereof, and expressly supersedes and replaces all prior
** and contemporaneous agreements, proposals, quotations, negotiations and communications, written
** or oral, between the parties relating to such subject matter.
**
**
** Software Author: Timesys Corporation (www.timesys.com)
**
** Summary: Custom media playback widget with control buttons
**
****************************************************************************/

#include "atmelmediaplayer.h"
#include "ui_atmelmediaplayer.h"
#include <QTime>

#if (QT_VERSION >= 0x050000)
#include <QVideoWidget>
#include "seekslider.h"
#include "volumeslider.h"
#endif // (QT_VERSION >= 0x050000)

/***
     ** Default constructor
     ** For Qt5: Uses QtMultimedia. Constructs QMediaPlayer objects, defines player decoration through stylesheet
     ** Connects QMediaPlayer signals with handling routins.
     ** For Qt4: Uses Phonon. Constructs Phonon objects, defines player decoration through stylesheet
     ** Connects Phonon signals with handling routins
     **/

AtmelMediaPlayer::AtmelMediaPlayer(QWidget *parent) :
    QWidget(parent),

    #if (QT_VERSION >= 0x050000)
    m_mediaObject(new QMediaPlayer(this)),
    videoWidget(new QVideoWidget(this)),
    #else
    videoWidget(new Phonon::VideoWidget(this)),
    #endif // (QT_VERSION >= 0x050000)

    playIcon(QIcon(":/resources/mediaPlayer/play.png")),
    pauseIcon(QIcon(":/resources/mediaPlayer/pause.png")),
    ui(new Ui::AtmelMediaPlayer)
{
    ui->setupUi(this);

#if (QT_VERSION >= 0x050000)
    m_mediaObject->setVideoOutput(videoWidget);

    SeekSlider *mediaSlider = new SeekSlider(this);
    mediaSlider->setMediaObject(m_mediaObject);

    VolumeSlider *volumeSlider = new VolumeSlider(this);
    volumeSlider->setMediaObject(m_mediaObject);

#else
    Phonon::SeekSlider* mediaSlider = new Phonon::SeekSlider(this);
    mediaSlider->setMediaObject(&mediaObject);

    Phonon::VolumeSlider* volumeSlider = new Phonon::VolumeSlider(&audioOutput);
#endif // (QT_VERSION >= 0x050000)

    if (isSmallResolution) {

        float wSFactor = 480.0 / 800.;
        float hSFactor = 272.0 / 480.;

        QSize size(ui->playButton->iconSize().width() * wSFactor, ui->playButton->iconSize().height() * hSFactor);
        ui->playButton->setIconSize(size);
        ui->stopButton->setIconSize(size);


        QFont font = ui->label->font();
        font.setPointSize(font.pointSize() * wSFactor);
        ui->label->setFont(font);
        font = ui->lengthLabel->font();
        font.setPointSize(font.pointSize() * wSFactor);
        ui->lengthLabel->setFont(font);
        font = ui->timeLabel->font();
        font.setPointSize(font.pointSize() * wSFactor);
        ui->timeLabel->setFont(font);
        ui->label->setMinimumWidth(ui->label->minimumWidth()*wSFactor);
        ui->lengthLabel->setMinimumWidth(ui->lengthLabel->minimumWidth()*wSFactor);
        ui->timeLabel->setMinimumWidth(ui->timeLabel->minimumWidth()*wSFactor);


        volumeSlider->setStyleSheet(
                    "QSlider:horizontal { height: 20px; border-image: none;}"
                    "QSlider::handle { image: url(:/resources/smallmediaPlayer/slider-dot.png);"
                    " margin: -20px 0;}"

                    " QSlider::groove { ;"
                    "border: 2px solid #CCD5CC;"
                    "background: white;"
                    " margin: 10px 0px 10px 0px;"
                    " border-radius: 3px;"
                    " height: 2px};"

                    " QIcon { height: 30px; width: 30px; border-image: none; }");

        ui->sliderWidget->setStyleSheet(
                    "QSlider:horizontal { height: 20px;}"
                    "QSlider::handle { image: url(:/resources/smallmediaPlayer/slider-dot.png);"
                    " margin: -20px 0;}"

                    " QSlider::groove { ;"
                    "border: 2px solid #CCD5CC;"
                    "background: white;"
                    " margin: 10px 0px 10px 0px;"
                    " border-radius: 3px;"
                    " height: 4px};");
    }
    else
    {
#if (QT_VERSION >= 0x050000)
        volumeSlider->setStyleSheetForSlider(
            #else
        volumeSlider->setStyleSheet(
            #endif // (QT_VERSION >= 0x050000)
                    "QSlider:horizontal { height: 40px; border-image: none;}"
                    "QSlider::handle { image: url(:/resources/mediaPlayer/slider-dot.png);"
                    " margin: -40px 0;}"

                    " QSlider::groove { ;"
                    "border: 2px solid #CCD5CC;"
                    "background: white;"
                    " margin: 20px 0px 20px 0px;"
                    " border-radius: 3px;"
                    " height: 2px};"

                    " QIcon { height: 60px; width: 60px; border-image: none; }");

        ui->sliderWidget->setStyleSheet(
                    "QSlider:horizontal { height: 40px;}"
                    "QSlider::handle { image: url(:/resources/mediaPlayer/slider-dot.png);"
                    " margin: -40px 0;}"

                    " QSlider::groove { ;"
                    "border: 2px solid #CCD5CC;"
                    "background: white;"
                    " margin: 20px 0px 20px 0px;"
                    " border-radius: 3px;"
                    " height: 4px};");
    }

    ui->sliderLayout->insertWidget(0, mediaSlider);
    ui->videoLayout->addWidget(videoWidget);
    ui->videoWindow->hide();
    ui->timeLabel->setText("0:00");
    ui->horizontalLayout->insertWidget(3, volumeSlider);

#if (QT_VERSION >= 0x050000)
    connect(m_mediaObject, SIGNAL(durationChanged(qint64)), this, SLOT(totalTime()));
    connect(m_mediaObject, SIGNAL(positionChanged(qint64)), this, SLOT(trackTime()));
    connect(m_mediaObject, SIGNAL(videoAvailableChanged(bool)), this, SLOT(newVideoToPlay(bool)));
    connect(m_mediaObject, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
            this, SLOT(updateMediaStatus(QMediaPlayer::MediaStatus)));
#else
    Phonon::createPath(&mediaObject, &audioOutput);
    Phonon::createPath(&mediaObject, videoWidget);

    connect(&mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTime()));
    connect(&mediaObject, SIGNAL(tick(qint64)), this, SLOT(trackTime()));
    connect(&mediaObject, SIGNAL(hasVideoChanged(bool)), this, SLOT(newVideoToPlay(bool)));
    connect(&mediaObject, SIGNAL(finished()), this, SLOT(videoPlaybackFinished()));
#endif // (QT_VERSION >= 0x050000)
}

/***
     ** Default destructor
     **/
AtmelMediaPlayer::~AtmelMediaPlayer()
{
    delete ui;
}

/***
     ** Make a playback object visible when there is a video to play
     **/
void AtmelMediaPlayer::newVideoToPlay(bool newVideo)
{
    ui->info->setVisible(!newVideo);
    ui->videoWindow->setVisible(newVideo);
}

/***
     ** Calculate/Display a total time for the current video
     **/
void AtmelMediaPlayer::totalTime()
{
    int sec, min, hour;

    long length =
        #if (QT_VERSION >= 0x050000)
            m_mediaObject->duration();
        #else
            mediaObject.totalTime();
        #endif // (QT_VERSION >= 0x050000)

    sec = length / 1000;
    min = sec / 60;
    hour = min / 60;

    QTime totalTime(hour%60, min%60, sec%60);

    QString displayFormat = "m:ss";

    ui->lengthLabel->setText(totalTime.toString(displayFormat));
}

/***
     ** Show tracked video playback time
     **/
void AtmelMediaPlayer::trackTime()
{
    int sec, min, hour;
    long pos =
        #if (QT_VERSION >= 0x050000)
            m_mediaObject->position();
        #else
            mediaObject.currentTime();
        #endif // (QT_VERSION >= 0x050000)

    sec = pos / 1000;
    min = sec / 60;
    hour = min / 60;

    QTime currentTime(hour%60, min%60, sec%60);

    QString timeFormat = "m:ss";

    ui->timeLabel->setText(currentTime.toString(timeFormat));
}

/***
     ** Function handler for the Play button
     ** switches playback state between play/pause
     **/
void AtmelMediaPlayer::on_playButton_clicked()
{
#if (QT_VERSION >= 0x050000)
    if (m_mediaObject->state() == QMediaPlayer::PlayingState) {
        m_mediaObject->pause();
        ui->playButton->setIcon(playIcon);
    } else {
        if (m_mediaObject->position() == m_mediaObject->duration())
            m_mediaObject->setPosition(0);
        m_mediaObject->play();
        ui->playButton->setIcon(pauseIcon);
    }
#else
    if (mediaObject.state() == Phonon::PlayingState){
        mediaObject.pause();
        ui->playButton->setIcon(playIcon);
    } else {
        if (mediaObject.currentTime() == mediaObject.totalTime())
            mediaObject.seek(0);
        mediaObject.play();
        ui->playButton->setIcon(pauseIcon);
    }
#endif // (QT_VERSION >= 0x050000)
}

/***
     ** Function handler for the Stop button
     **/
void AtmelMediaPlayer::on_stopButton_clicked()
{
#if (QT_VERSION >= 0x050000)
    m_mediaObject->setPosition(0);
    m_mediaObject->stop();
#else
    mediaObject.seek(0);
    mediaObject.stop();
#endif // (QT_VERSION >= 0x050000)
    ui->playButton->setIcon(playIcon);
    ui->timeLabel->setText("0:00");
}

/***
     ** Sets the path to the media file that should play next in this widget
     ** Starts the playback
     **/
void AtmelMediaPlayer::setFileToPlay(const QString &path)
{
#if (QT_VERSION >= 0x050000)
    if (m_mediaObject->state() == QMediaPlayer::PlayingState)
        m_mediaObject->stop();
    m_mediaObject->setMedia(QUrl::fromLocalFile(path));
    m_mediaObject->play();
#else
    if (mediaObject.state() == 2) // TODO: avoid 2
        mediaObject.stop();
    mediaObject.setCurrentSource(Phonon::MediaSource(path));
    mediaObject.play();
#endif // (QT_VERSION >= 0x050000)
    ui->playButton->setIcon(pauseIcon);
}

/***
     ** Signal handler for when the video is done playing
     **/
void AtmelMediaPlayer::videoPlaybackFinished()
{
    on_stopButton_clicked();
}

/***
     ** Public function to stop playback from outside of this object
     **/
void AtmelMediaPlayer::stopPlayback()
{
    on_stopButton_clicked();
}

#if (QT_VERSION >= 0x050000)
void AtmelMediaPlayer::updateMediaStatus(QMediaPlayer::MediaStatus status)
{
    switch(status) {
    case QMediaPlayer::UnknownMediaStatus:
        qDebug("Unknown Media Status");
        break;
    case QMediaPlayer::NoMedia:
        qDebug("No Media");
        break;
    case QMediaPlayer::LoadingMedia:
        qDebug("In Loading state");
        break;
    case QMediaPlayer::LoadedMedia:
        qDebug("Media has been Loaded");
        break;
    case QMediaPlayer::StalledMedia:
        qDebug("Media is stalled");
        break;
    case QMediaPlayer::BufferingMedia:
        qDebug("In Buffering state");
        break;
    case QMediaPlayer::BufferedMedia:
        qDebug("Media has been buffered");
        break;
    case QMediaPlayer::EndOfMedia:
        qDebug("End of Media");
        videoPlaybackFinished();
        break;
    case QMediaPlayer::InvalidMedia:
        qDebug("Invalid Media");
        break;
    }
}
#endif // (QT_VERSION >= 0x050000)
